/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package client.logic;

import com.cse.p2p.parser.*;
import java.util.List;
import java.util.List;
import java.util.Random;

/**
 *
 * @author TuyetNgan
 */
public class ClientLogicImplement {

	private static final Integer fileID = 0;
	private static final Integer pieceID = 1;
	private static final Integer ipAddress = 2;
	private static final Integer upSpeed = 3;
	private static final Integer sizeOfDatabase = 100;
	private static Boolean debug = true;
    
    public static int choosePiecesSize(){
        // default 256KB     
        return 256;
    }
    
    public static int getNumberOfPiece(long FILE_SIZE, int PIECE_SIZE){
        if(FILE_SIZE % PIECE_SIZE == 0) 
            return (int) FILE_SIZE/PIECE_SIZE;
        else 
            return ((int)FILE_SIZE/PIECE_SIZE)+1;
    }
    
	public static class pieceDatabase {

		String[][] pieceInfo = new String[ 4 ][ sizeOfDatabase ];
		String piece = null;
	}
    /*
	public static void main( String[] args ) {
		if ( debug ) {
			System.out.println( "start debug mode" );
		}
        String requestFile = "A"; // example
		String[] a = findPieceAndPeer( requestFile );
		if ( debug ) {
			System.out.println( "FILE_ID,PIECE_ID,IP address : " + a[0] + " - " + a[1] + " - " + a[2] );
		}

	}

     * 
     */

	public static String[] findPieceAndPeer( List<PeerInfo> info , String requestFile) {

		/**
		 * data [0][x]: FILE_ID
		 * data [1][x]: PIECE_ID
		 * data [2][x]: IP address
		 * data [3][x]: upload speed @hieu: Ngan, how do we get the UL speed? I think it must be calculated later, when you "ping" to each peer
		 */
		String[][] data = new String[ 4 ][ sizeOfDatabase ];
        
		if ( debug ) {
			data[0][0] = "A";
			data[1][0] = "A1";
			data[2][0] = "1";
			data[3][0] = "900";

			data[0][1] = "A";
			data[1][1] = "A2";
			data[2][1] = "1";
			data[3][1] = "200";

			data[0][2] = "B";
			data[1][2] = "B1";
			data[2][2] = "2";
			data[3][2] = "900";

			data[0][3] = "A";
			data[1][3] = "A2";
			data[2][3] = "2";
			data[3][3] = "100";

			data[0][4] = "A";
			data[1][4] = "A1";
			data[2][4] = "2";
			data[3][4] = "800";
		}
		/* Convert peerInfo to data[][] */
        int index = 0;
        while(!info.isEmpty()){
            PeerInfo curretnPeer = info.remove(index++);
            int[] PIECE_ID = curretnPeer.getPieces();
            for(int i = 0 ; i < sizeOfDatabase ; i++){
                data[0][i] = Integer.toString(curretnPeer.getFileID());
                data[1][i] = Integer.toString(PIECE_ID[i]);
                data[2][i] = curretnPeer.getIP();
                //data[3][i] = 
            }
        }
		/** End of parsing */

	

		/** 
		 * Algorithm to find suitable piece :
		 *  1) rarest first
		 *  2) choke 
		 *  3) random
		 */
		return findPiece( data, requestFile );
	}

	private static String[] findPiece( String[][] data, String FILE_ID ) {
		String[] result = new String[ 3 ];
		Integer i, j;
		pieceDatabase[] tempPieceArray = new pieceDatabase[ sizeOfDatabase ]; // set of rarest pieces
		String[][] tempIP = new String[ 4 ][ sizeOfDatabase ];


		//statictis pieces of FILE_ID and find the rarest piece
		Integer countIP = 0, min = Integer.MAX_VALUE, countPiece = 0;
		String tempPiece;
		Boolean flag;
		for ( i = 0; i < data[pieceID].length; i++ ) {
			if ( data[fileID][i] != null && data[fileID][i].equals( FILE_ID ) ) {
				tempPiece = data[pieceID][i];
				flag = false;
				for ( j = 0; j < tempPieceArray.length; j++ ) {
					if ( tempPieceArray[j] != null && tempPieceArray[j].piece.equals( tempPiece ) ) {
						flag = true;
						break;
					}
				}
				if ( flag == false ) {
					for ( j = 0; j < data[pieceID].length; j++ ) {
						if ( data[fileID][j] != null && data[pieceID][j].equals( tempPiece )
							 && data[fileID][j].equals( FILE_ID ) ) {
							tempIP[ipAddress][countIP] = data[ipAddress][j];
							tempIP[upSpeed][countIP] = data[upSpeed][j];
							countIP++;
						}
					}
					if ( countIP <= min ) {
						if ( countIP == min ) {
							countPiece++;
						}
						else {
							countPiece = 1;
						}
						tempPieceArray[countPiece - 1] = new pieceDatabase();
						tempPieceArray[countPiece - 1].pieceInfo = tempIP;
						tempPieceArray[countPiece - 1].piece = tempPiece;
						min = countIP;
					}
					if ( debug ) {
						System.out.println( tempPiece + ", countIP = "
											+ countIP + " , countPiece = " + countPiece );
						System.out.print( "\tIP,upspeed: " );
						for ( i = 0; i < countPiece; i++ ) {
							for ( j = 0; j < tempPieceArray[i].pieceInfo[ipAddress].length; j++ ) {
								if ( tempPieceArray[i].piece.equals( tempPiece )
									 && tempPieceArray[i].pieceInfo[ipAddress][j] != null ) {
									System.out.print( tempPieceArray[i].pieceInfo[ipAddress][j] + " - "
													  + tempPieceArray[i].pieceInfo[upSpeed][j] + ", " );
								}

							}
						}
						System.out.print( "\n" );
					}
					countIP = 0;
				}
			}
		}


		Integer num;
		if ( countPiece > 1 ) // have many rare pieces
		{
			num = randomNumber( countPiece );
		}
		else {
			num = 0;
		}
		if ( debug ) {
			System.out.println( "RanNum : " + num + "/" + countPiece );
		}
		result[ipAddress] = findPeer( tempPieceArray[num].pieceInfo );
		result[pieceID] = tempPieceArray[num].piece;
		if ( result[ipAddress] == null || result[pieceID] == null ) {
			return null;
		}

		result[fileID] = FILE_ID;
		return result;
	}

	private static String findPeer( String[][] array ) {
		String[] temp = new String[ array.length ];
		Integer i, u, count = 0, max = 0;
		for ( i = 0; i < array[upSpeed].length; i++ ) {
			if ( array[upSpeed][i] != null
				 && ( u = Integer.parseInt( array[upSpeed][i] ) ) >= max ) {
				if ( u == max ) {
					count++;
				}
				else {
					count = 0;
				}
				max = u;
				temp[count] = array[ipAddress][i];
			}
		}
		if ( max == 0 ) // no peer 
		{
			return null;
		}
		else if ( count > 0 )// many peers which have same upload speed 
		{
			return temp[randomNumber( count + 1 )];
		}
		else // only one peer chosen
		{
			return temp[0];
		}
	}

	private static Integer randomNumber( Integer size ) {
		Random ran = new Random();
		return ran.nextInt( size );
	}

	// TO DO : wait for LocalFile and Database
	public Boolean checkPieceInDatabase( String FILE_ID, String PIECE_ID ) {
		return true;
	}

	public Boolean checkPieceInLocalFile( String FILE_ID, String PIECE_ID ) {
		return true;
	}

	public String[] findFileInDatabse( String FILE_ID ) {
		return new String[ 1 ];
	}

	public Boolean checkListPieceInLocalFile( String[] PIECE_ID ) {
		return true;
	}
}
